package com.liqw.core;

import lombok.extern.slf4j.Slf4j;
import org.openqa.selenium.By;
import org.openqa.selenium.JavascriptExecutor;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;

import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.StringJoiner;
import java.util.concurrent.TimeUnit;

/**
 * 直播课管理器（处理直播课导航、列表获取和视频播放）
 */
@Slf4j
public class LiveCourseManager {
    private final WebDriver driver;

    public LiveCourseManager(WebDriver driver) {
        this.driver = driver;
    }

    /**
     * 导航到直播课页面并播放所有已录制的直播课
     */
    public void playRecordedLiveCourses() {
        // 导航到直播课页面
        boolean navigateSuccess = navigateToLiveCoursesPage();
        if (!navigateSuccess) {
            log.error("无法导航到直播课页面");
            return;
        }

        // 查找并播放已录制的直播课
        findAndPlayRecordedCourses();
    }

    /**
     * 导航到直播课页面
     */
    boolean navigateToLiveCoursesPage() {
        try {
// 尝试通过菜单链接导航
            WebElement liveMenuLink = WebDriverUtils.waitForElementVisible(driver,
                    By.xpath(SelectorConstants.XPATH_LIVE_COURSE_MENU));

            if (liveMenuLink != null) {
                log.info("找到直播课菜单，点击导航");
                boolean clickSuccess = WebDriverUtils.clickElement(driver, liveMenuLink);

                if (clickSuccess) {
                    // 切换到本学期课表tab
                    log.info("直播课页面加载成功，尝试切换到本学期课表tab");
                    switchToCurrentSemesterTab();
                }

                return clickSuccess;
            }
            return false;
        } catch (Exception e) {
            log.error("导航到直播课页面时发生异常", e);
            return false;
        }
    }

    /**
     * 切换到本学期课表tab
     */
    private void switchToCurrentSemesterTab() {
        try {
            // 尝试多种可能的选择器来查找本学期课表tab
            String[] semesterTabSelectors = {
                    "li.card-item:contains('当前学期')",
            };

            WebElement semesterTab = null;

            // 尝试每种选择器
            for (String selector : semesterTabSelectors) {
                try {
                    semesterTab = WebDriverUtils.waitForElementVisible(driver, By.cssSelector(selector));
                    if (semesterTab != null) {
                        log.info("找到本学期课表tab，点击切换");
                        WebDriverUtils.clickElement(driver, semesterTab);
                        // 等待tab切换完成
                        TimeUnit.SECONDS.sleep(2);
                        return;
                    }
                } catch (Exception e) {
                    // 尝试下一种选择器
                    continue;
                }
            }

            // 如果CSS选择器失败，尝试使用XPATH
            try {
                semesterTab = WebDriverUtils.waitForElementVisible(driver,
                        By.xpath("//*[contains(text(), '本学期') or contains(text(), '当前学期')]")
                );
                if (semesterTab != null) {
                    log.info("通过XPATH找到本学期课表tab，点击切换");
                    WebDriverUtils.clickElement(driver, semesterTab);
                    TimeUnit.SECONDS.sleep(2);
                } else {
                    log.warn("未找到本学期课表tab，将使用默认显示的课表");
                }
            } catch (Exception e) {
                log.warn("切换到本学期课表tab失败，将使用默认显示的课表");
            }
        } catch (Exception e) {
            log.error("切换到本学期课表tab时发生异常", e);
        }
    }

    /**
     * 查找并播放已录制的直播课
     */
    private void findAndPlayRecordedCourses() {
        try {
            // 等待直播课列表加载
            WebDriverUtils.waitForElementVisible(driver,
                    By.cssSelector(SelectorConstants.CSS_LIVE_COURSE_LIST_CONTAINER));

            // 获取所有直播课项
            List<WebElement> liveCourseItems = driver.findElements(
                    By.cssSelector(SelectorConstants.CSS_LIVE_COURSE_ITEM));

            log.info("共发现 {} 个直播课", liveCourseItems.size());

            for (WebElement courseItem : liveCourseItems) {
                try {
                    // 获取直播课信息
                    String courseName = getCourseTitle(courseItem);
                    String courseStatus = getCourseStatus(courseItem);


                    log.info("直播课名称: {}", courseName);
                    log.info("直播课状态: {}", courseStatus);
// 只处理已录制（可重播）的课程
                    if (isRecordedCourse(courseStatus)) {
                        log.info("找到可重播的录制课程，开始播放");
                        playLiveCourse(courseItem, courseName);
                    } else {
                        log.info("课程不可重播或未录制，跳过");
                    }
                } catch (Exception e) {
                    log.error("处理直播课时发生异常", e);
                }
            }
        } catch (Exception e) {
            log.error("查找直播课时发生异常", e);
        }
    }

    private WebElement getCourseButton(WebElement courseItem) {
        try {
            return courseItem.findElement(
                    By.xpath(SelectorConstants.XPATH_LIVE_COURSE_PLAY_BUTTON));
        } catch (Exception e) {
            log.warn("获取直播课标题失败，使用默认名称");
            return null;
        }
    }

    /**
     * 获取直播课标题
     */
    String getCourseTitle(WebElement courseItem) {
        try {
            WebElement titleElement = courseItem.findElement(
                    By.cssSelector(SelectorConstants.CSS_LIVE_COURSE_TITLE));
            return titleElement.getText().trim();
        } catch (Exception e) {
            log.warn("获取直播课标题失败，使用默认名称");
            return "未知直播课";
        }
    }

    /**
     * 获取直播课状态
     */
    String getCourseStatus(WebElement courseItem) {
        try {
            WebElement statusElement = courseItem.findElement(
                    By.xpath(SelectorConstants.XPATH_LIVE_COURSE_STATUS));
            return statusElement.getText().trim();
        } catch (Exception e) {
            log.warn("获取直播课状态失败");
            return "";
        }
    }

    /**
     * 判断课程是否为已录制可重播的课程
     */
    boolean isRecordedCourse(String status) {
        String statusLower = status.toLowerCase();

        // 检查状态或名称中是否包含已录制/重播/回放等关键词
        return statusLower.contains("直播结束") ||
                statusLower.contains("重播") ||
                statusLower.contains("回放") ||
                statusLower.contains("已结束") ||
                statusLower.contains("record") ||
                statusLower.contains("playback");
    }

    // 添加直接播放方法，不重新打开窗口
    public void playCourseContent(String courseName) {
        try {
            // 等待视频播放器加载
            WebElement videoPlayer = WebDriverUtils.waitForElementVisible(driver,
                    By.cssSelector(SelectorConstants.LIVE_VIDEO_PLAYER));

            if (videoPlayer != null) {
                // 播放逻辑...（复用现有代码）
            }
        } catch (Exception e) {
            log.error("播放课程内容时发生异常", e);
        }
    }

    /**
     * 播放单个直播课
     */
    private void playLiveCourse(WebElement courseItem, String courseName) {
        String originalHandle = driver.getWindowHandle();
        String newWindowHandle = null;
        boolean videoCompleted = false;

        try {
            // 等待新窗口打开并切换（使用正确的方法）
            Set<String> originalHandles = driver.getWindowHandles();

            // 查找播放按钮
            WebElement playButton = findPlayButton(courseItem);
            if (playButton == null) {
                log.error("未找到播放按钮");
                return;
            }

            // 点击播放按钮并打开新窗口
            boolean clickSuccess = WebDriverUtils.clickElement(driver, playButton);
            if (!clickSuccess) {
                log.error("点击播放按钮失败");
                return;
            }


            newWindowHandle = WebDriverUtils.switchToNewWindow(originalHandles, driver);
            if (newWindowHandle == null) {
                log.error("新窗口未打开");
                return;
            }
            // 注意：switchToNewWindow方法已经执行了switchTo操作，不需要再调用driver.switchTo().window(newWindowHandle);

            doPlay(courseName, videoCompleted);
        } finally {
            // 关闭直播课窗口并切换回原窗口
            WebDriverUtils.closeWindowAndSwitchBack(driver, newWindowHandle, originalHandle);
        }
    }

    void doPlay(String courseName, boolean videoCompleted) {
        // 等待视频播放器加载
        WebElement videoPlayer = WebDriverUtils.waitForElementVisible(driver,
                By.cssSelector(SelectorConstants.LIVE_VIDEO_PLAYER));

        if (videoPlayer != null) {
            // 播放逻辑...
            StringJoiner playScriptJoiner = new StringJoiner("\n");
            playScriptJoiner.add("try {");
            playScriptJoiner.add("  // 尝试直接播放视频");
            playScriptJoiner.add("  var videos = document.querySelectorAll('video');");
            playScriptJoiner.add("  var played = false;");
            playScriptJoiner.add("  ");
            playScriptJoiner.add("  // 尝试播放所有找到的video元素");
            playScriptJoiner.add("  for (var i = 0; i < videos.length; i++) {");
            playScriptJoiner.add("    var video = videos[i];");
            playScriptJoiner.add("    try {");
            playScriptJoiner.add("      video.play();");
            playScriptJoiner.add("      played = true;");
            playScriptJoiner.add("      console.log('视频开始播放');");
            playScriptJoiner.add("      break;");
            playScriptJoiner.add("    } catch (e) {");
            playScriptJoiner.add("      console.warn('播放video元素失败: ' + e.message);");
            playScriptJoiner.add("    }");
            playScriptJoiner.add("  }");
            playScriptJoiner.add("  ");
            playScriptJoiner.add("  // 如果标准video播放失败，尝试点击播放按钮");
            playScriptJoiner.add("  if (!played) {");
            playScriptJoiner.add("    var playButtons = document.querySelectorAll('.play, .playButton, .play-icon, .vjs-play-control, .jw-icon-play');");
            playScriptJoiner.add("    for (var j = 0; j < playButtons.length; j++) {");
            playScriptJoiner.add("      if (playButtons[j].offsetParent !== null) {");
            playScriptJoiner.add("        playButtons[j].click();");
            playScriptJoiner.add("        played = true;");
            playScriptJoiner.add("        console.log('点击播放按钮');");
            playScriptJoiner.add("        break;");
            playScriptJoiner.add("      }");
            playScriptJoiner.add("    }");
            playScriptJoiner.add("  }");
            playScriptJoiner.add("  ");
            playScriptJoiner.add("  // 尝试支持video.js播放器");
            playScriptJoiner.add("  if (!played && typeof videojs !== 'undefined') {");
            playScriptJoiner.add("    var players = videojs.players;");
            playScriptJoiner.add("    for (var playerId in players) {");
            playScriptJoiner.add("      if (players.hasOwnProperty(playerId)) {");
            playScriptJoiner.add("        try {");
            playScriptJoiner.add("          players[playerId].play();");
            playScriptJoiner.add("          played = true;");
            playScriptJoiner.add("          console.log('启动video.js播放器');");
            playScriptJoiner.add("          break;");
            playScriptJoiner.add("        } catch (e) {");
            playScriptJoiner.add("          console.warn('播放video.js失败: ' + e.message);");
            playScriptJoiner.add("        }");
            playScriptJoiner.add("      }");
            playScriptJoiner.add("    }");
            playScriptJoiner.add("  }");
            playScriptJoiner.add("  ");
            playScriptJoiner.add("  return played;");
            playScriptJoiner.add("}");
            playScriptJoiner.add("catch(e) {");
            playScriptJoiner.add("  console.error('播放脚本执行失败: ' + e.message);");
            playScriptJoiner.add("  return false;");
            playScriptJoiner.add("}");

            Boolean played = (Boolean) ((JavascriptExecutor) driver).executeScript(playScriptJoiner.toString());
            if (played != null && played) {
                log.info("视频已开始播放");
            } else {
                log.error("播放脚本执行失败");
            }

            // 获取视频总长度，最多尝试5次
            Double videoDuration = null;
            for (int attempt = 0; attempt < 5 && videoDuration == null; attempt++) {
                videoDuration = getVideoDuration(driver);
                if (videoDuration == null) {
                    try {
                        TimeUnit.SECONDS.sleep(2);
                    } catch (InterruptedException e) {
                        throw new RuntimeException(e);
                    }
                }
            }

            // 计算观看时长（总长度的98%或默认30分钟）
            int targetMinutes = 30; // 默认30分钟
            if (videoDuration != null && videoDuration > 0) {
                targetMinutes = (int) (videoDuration * 0.98 / 60);
                if (targetMinutes < 5) {
                    targetMinutes = 5; // 最少观看5分钟
                }
                if (targetMinutes > 120) {
                    targetMinutes = 120; // 最多观看2小时
                }
            }

            int maxCheckIntervals = targetMinutes * 2; // 每30秒检查一次
            int targetInterval = targetMinutes * 2; // 目标观看时间对应的间隔数

            for (int i = 0; i < maxCheckIntervals; i++) {
                try {
                    // 这里就是原来漂浮在方法外部的代码
                    TimeUnit.SECONDS.sleep(30);
                    // 检查视频播放状态并在暂停时恢复播放
                    checkAndResumeVideoPlayback(driver, videoPlayer);

                    // 计算已观看时间（秒数）
                    int watchedSeconds = (i + 1) * 30;
                    // 转换为小时:分钟:秒格式
                    int hours = watchedSeconds / 3600;
                    int minutes = (watchedSeconds % 3600) / 60;
                    int seconds = watchedSeconds % 60;
                    String timeFormatted;
                    if (hours > 0) {
                        timeFormatted = String.format("%02d:%02d:%02d", hours, minutes, seconds);
                    } else if (minutes > 0) {
                        timeFormatted = String.format("%02d:%02d", minutes, seconds);
                    } else {
                        timeFormatted = String.format("00:%02d", seconds);
                    }

                    // 尝试获取实际播放进度
                    Double progress = getVideoProgress(driver);
                    if (progress != null) {
                        StringJoiner progressLogJoiner = new StringJoiner(" ");
                        progressLogJoiner.add("已观看");
                        progressLogJoiner.add(timeFormatted);
                        progressLogJoiner.add("，当前进度:");
                        progressLogJoiner.add(String.format("%.1f", progress));
                        progressLogJoiner.add("%");
                        log.info(progressLogJoiner.toString());
                        // 如果进度达到98%，提前结束
                        if (progress >= 98.0) {
                            StringJoiner completeLogJoiner = new StringJoiner(" ");
                            completeLogJoiner.add("直播课");
                            completeLogJoiner.add(courseName);
                            completeLogJoiner.add("进度已达到98%");
                            completeLogJoiner.add("，提前结束观看");
                            log.info(completeLogJoiner.toString());
                            videoCompleted = true;
                            break;
                        }
                    } else {
                        StringJoiner continueLogJoiner = new StringJoiner(" ");
                        continueLogJoiner.add("已观看");
                        continueLogJoiner.add(timeFormatted);
                        continueLogJoiner.add("，继续观看...");
                        log.info(continueLogJoiner.toString());
                    }

                    // 检查是否达到目标观看时间（98%的总时间）
                    if (i >= targetInterval) {
                        StringJoiner targetLogJoiner = new StringJoiner(" ");
                        targetLogJoiner.add("直播课");
                        targetLogJoiner.add(courseName);
                        targetLogJoiner.add("已观看达到目标时长");
                        targetLogJoiner.add("，提前结束观看");
                        log.info(targetLogJoiner.toString());
                        videoCompleted = true;
                        break;
                    }

                    // 每5分钟滚动页面并点击视频区域，防止页面超时或视频暂停
                    if (i % 10 == 9) { // 每5分钟执行一次（10个30秒间隔）
                        try {
                            StringJoiner checkScriptJoiner = new StringJoiner("\n");
                            checkScriptJoiner.add("// 滚动页面防止超时");
                            checkScriptJoiner.add("window.scrollBy(0, 100);");
                            checkScriptJoiner.add("window.scrollBy(0, -100);");
                            checkScriptJoiner.add("// 点击视频确保继续播放");
                            checkScriptJoiner.add("if (arguments[0]) {");
                            checkScriptJoiner.add("    arguments[0].click();");
                            checkScriptJoiner.add("}");
                            ((JavascriptExecutor) driver).executeScript(checkScriptJoiner.toString(), videoPlayer);
                        } catch (Exception e) {
                            log.warn("执行页面活动脚本时出错: {}", e.getMessage());
                            // 继续执行，不中断主流程
                        }
                    }
                } catch (InterruptedException e) {
                    Thread.currentThread().interrupt();
                    break;
                }
            }

            if (videoCompleted) {
                StringJoiner finalLogJoiner = new StringJoiner(" ");
                finalLogJoiner.add("直播课");
                finalLogJoiner.add(courseName);
                finalLogJoiner.add("已接近完成");
                finalLogJoiner.add("，关闭播放页面");
                log.info(finalLogJoiner.toString());
            } else {
                log.info("直播课 {} 观看时间已到", courseName);
            }
        } else {
            log.error("未找到视频播放器元素");
        }
    }

    /**
     * 检查视频播放状态并在暂停时恢复播放
     */
    private void checkAndResumeVideoPlayback(WebDriver driver, WebElement videoPlayer) {
        try {
            // 使用StringJoiner构建检查和恢复播放的JavaScript
            StringJoiner checkStatusScriptJoiner = new StringJoiner("\n");
            checkStatusScriptJoiner.add("try {");
            checkStatusScriptJoiner.add("  // 检查标准video元素是否暂停");
            checkStatusScriptJoiner.add("  var videos = document.querySelectorAll('video');");
            checkStatusScriptJoiner.add("  var wasPaused = false;");
            checkStatusScriptJoiner.add("  ");
            checkStatusScriptJoiner.add("  // 检查并恢复标准video元素的播放");
            checkStatusScriptJoiner.add("  for (var i = 0; i < videos.length; i++) {");
            checkStatusScriptJoiner.add("    var video = videos[i];");
            checkStatusScriptJoiner.add("    if (video.paused && video.currentTime > 0 && !isNaN(video.duration) && video.currentTime < video.duration - 1) {");
            checkStatusScriptJoiner.add("      video.play();");
            checkStatusScriptJoiner.add("      wasPaused = true;");
            checkStatusScriptJoiner.add("      console.log('恢复video元素播放');");
            checkStatusScriptJoiner.add("    }");
            checkStatusScriptJoiner.add("  }");
            checkStatusScriptJoiner.add("  ");
            checkStatusScriptJoiner.add("  // 检查video.js播放器");
            checkStatusScriptJoiner.add("  if (typeof videojs !== 'undefined') {");
            checkStatusScriptJoiner.add("    var players = videojs.players;");
            checkStatusScriptJoiner.add("    for (var playerId in players) {");
            checkStatusScriptJoiner.add("      if (players.hasOwnProperty(playerId)) {");
            checkStatusScriptJoiner.add("        var player = players[playerId];");
            checkStatusScriptJoiner.add("        if (player.paused() && player.currentTime() > 0 && player.currentTime() < player.duration() - 1) {");
            checkStatusScriptJoiner.add("          player.play();");
            checkStatusScriptJoiner.add("          wasPaused = true;");
            checkStatusScriptJoiner.add("          console.log('恢复video.js播放器播放');");
            checkStatusScriptJoiner.add("        }");
            checkStatusScriptJoiner.add("      }");
            checkStatusScriptJoiner.add("    }");
            checkStatusScriptJoiner.add("  }");
            checkStatusScriptJoiner.add("  ");
            checkStatusScriptJoiner.add("  // 如果没有找到暂停的视频，但提供了播放器元素，尝试点击它");
            checkStatusScriptJoiner.add("  if (!wasPaused && arguments[0]) {");
            checkStatusScriptJoiner.add("    // 尝试点击播放按钮（如果存在）");
            checkStatusScriptJoiner.add("    var playBtns = document.querySelectorAll('.play, .playButton, .play-icon, .vjs-play-control, .jw-icon-play');");
            checkStatusScriptJoiner.add("    for (var j = 0; j < playBtns.length; j++) {");
            checkStatusScriptJoiner.add("      if (playBtns[j].offsetParent !== null) {");
            checkStatusScriptJoiner.add("        playBtns[j].click();");
            checkStatusScriptJoiner.add("        wasPaused = true;");
            checkStatusScriptJoiner.add("        console.log('点击播放按钮恢复播放');");
            checkStatusScriptJoiner.add("        break;");
            checkStatusScriptJoiner.add("      }");
            checkStatusScriptJoiner.add("    }");
            checkStatusScriptJoiner.add("  }");
            checkStatusScriptJoiner.add("  ");
            checkStatusScriptJoiner.add("  return wasPaused;");
            checkStatusScriptJoiner.add("}");
            checkStatusScriptJoiner.add("catch(e) {");
            checkStatusScriptJoiner.add("  console.error('检查视频播放状态时出错: ' + e.message);");
            checkStatusScriptJoiner.add("  return false;");
            checkStatusScriptJoiner.add("}");

            Boolean wasPaused = (Boolean) ((JavascriptExecutor) driver).executeScript(checkStatusScriptJoiner.toString(), videoPlayer);
            if (wasPaused != null && wasPaused) {
                log.info("检测到视频暂停，已自动恢复播放");
            }
        } catch (Exception e) {
            log.warn("检查和恢复视频播放状态时发生异常: {}", e.getMessage());
            // 继续执行，不中断主流程
        }
    }

    /**
     * 尝试多种方法获取视频播放进度
     */
    private Double getVideoProgress(WebDriver driver) {
        try {
            // 方法1: 尝试从标准video元素获取进度
            StringJoiner script1Joiner = new StringJoiner("\n");
            script1Joiner.add("try {");
            script1Joiner.add("  // 查找页面中所有的video元素");
            script1Joiner.add("  var videos = document.querySelectorAll('video');");
            script1Joiner.add("  for (var i = 0; i < videos.length; i++) {");
            script1Joiner.add("    var video = videos[i];");
            script1Joiner.add("    if (video.duration > 0 && !isNaN(video.currentTime)) {");
            script1Joiner.add("      return {progress: (video.currentTime / video.duration) * 100, duration: video.duration};");
            script1Joiner.add("    }");
            script1Joiner.add("  }");
            script1Joiner.add("  return null;");
            script1Joiner.add("}");
            script1Joiner.add("catch(e) {");
            script1Joiner.add("  console.error('获取视频进度失败: ' + e.message);");
            script1Joiner.add("  return null;");
            script1Joiner.add("}");

            Object result = ((JavascriptExecutor) driver).executeScript(script1Joiner.toString());
            if (result instanceof Map) {
                Map<?, ?> mapResult = (Map<?, ?>) result;
                if (mapResult.containsKey("progress")) {
                    Object progressObj = mapResult.get("progress");
                    if (progressObj instanceof Long) {
                        return ((Long) progressObj).doubleValue();
                    } else if (progressObj instanceof Double) {
                        return (Double) progressObj;
                    } else if (progressObj instanceof Number) {
                        return ((Number) progressObj).doubleValue();
                    }
                }
            }

            // 方法2: 尝试从常见的播放器框架获取进度
            StringJoiner script2Joiner = new StringJoiner("\n");
            script2Joiner.add("try {");
            script2Joiner.add("  // 尝试获取video.js播放器进度");
            script2Joiner.add("  if (typeof videojs !== 'undefined') {");
            script2Joiner.add("    var players = videojs.players;");
            script2Joiner.add("    for (var playerId in players) {");
            script2Joiner.add("      if (players.hasOwnProperty(playerId)) {");
            script2Joiner.add("        var player = players[playerId];");
            script2Joiner.add("        if (player.duration() > 0) {");
            script2Joiner.add("          return {progress: (player.currentTime() / player.duration()) * 100, duration: player.duration()};");
            script2Joiner.add("        }");
            script2Joiner.add("      }");
            script2Joiner.add("    }");
            script2Joiner.add("  }");
            script2Joiner.add("  // 尝试获取其他常见播放器进度");
            script2Joiner.add("  var progressBars = document.querySelectorAll('.video-progress-bar, .progress-bar, .jw-progress');");
            script2Joiner.add("  for (var i = 0; i < progressBars.length; i++) {");
            script2Joiner.add("    var bar = progressBars[i];");
            script2Joiner.add("    var width = bar.style.width || bar.getAttribute('aria-valuenow');");
            script2Joiner.add("    if (width) {");
            script2Joiner.add("      // 处理百分比格式或数值格式");
            script2Joiner.add("      if (width.indexOf('%') > -1) {");
            script2Joiner.add("        return {progress: parseFloat(width), duration: null};");
            script2Joiner.add("      } else {");
            script2Joiner.add("        return {progress: parseFloat(width), duration: null};");
            script2Joiner.add("      }");
            script2Joiner.add("    }");
            script2Joiner.add("  }");
            script2Joiner.add("  return null;");
            script2Joiner.add("}");
            script2Joiner.add("catch(e) {");
            script2Joiner.add("  console.error('获取播放器进度失败: ' + e.message);");
            script2Joiner.add("  return null;");
            script2Joiner.add("}");

            result = ((JavascriptExecutor) driver).executeScript(script2Joiner.toString());
            if (result instanceof Map) {
                Map<?, ?> mapResult = (Map<?, ?>) result;
                if (mapResult.containsKey("progress")) {
                    Object progressObj = mapResult.get("progress");
                    if (progressObj instanceof Long) {
                        return ((Long) progressObj).doubleValue();
                    } else if (progressObj instanceof Double) {
                        return (Double) progressObj;
                    } else if (progressObj instanceof Number) {
                        return ((Number) progressObj).doubleValue();
                    }
                }
            }
            // 方法3: 尝试从时间显示元素计算进度
            StringJoiner script3Joiner = new StringJoiner("\n");
            script3Joiner.add("try {");
            script3Joiner.add("  // 查找当前时间和总时间显示元素");
            script3Joiner.add("  var currentTime = null;");
            script3Joiner.add("  var totalTime = null;");
            script3Joiner.add("  ");
            script3Joiner.add("  // 尝试常见的时间显示选择器");
            script3Joiner.add("  var timeElements = document.querySelectorAll('.current-time, .time-current, .time-elapsed, .video-time-current');");
            script3Joiner.add("  if (timeElements.length > 0) {");
            script3Joiner.add("    currentTime = timeElements[0].textContent.trim();");
            script3Joiner.add("  }");
            script3Joiner.add("  ");
            script3Joiner.add("  var durationElements = document.querySelectorAll('.duration, .time-duration, .video-time-total');");
            script3Joiner.add("  if (durationElements.length > 0) {");
            script3Joiner.add("    totalTime = durationElements[0].textContent.trim();");
            script3Joiner.add("  }");
            script3Joiner.add("  ");
            script3Joiner.add("  // 如果找到时间文本，尝试解析");
            script3Joiner.add("  if (currentTime && totalTime) {");
            script3Joiner.add("    // 解析时间格式 (例如: 1:23:45 或 23:45)");
            script3Joiner.add("    function parseTime(timeStr) {");
            script3Joiner.add("      var parts = timeStr.split(':').map(Number);");
            script3Joiner.add("      if (parts.length === 3) {");
            script3Joiner.add("        return parts[0] * 3600 + parts[1] * 60 + parts[2]; // 小时:分钟:秒");
            script3Joiner.add("      } else if (parts.length === 2) {");
            script3Joiner.add("        return parts[0] * 60 + parts[1]; // 分钟:秒");
            script3Joiner.add("      }");
            script3Joiner.add("      return 0;");
            script3Joiner.add("    }");
            script3Joiner.add("    ");
            script3Joiner.add("    var currentSecs = parseTime(currentTime);");
            script3Joiner.add("    var totalSecs = parseTime(totalTime);");
            script3Joiner.add("    ");
            script3Joiner.add("    if (totalSecs > 0) {");
            script3Joiner.add("      return {progress: (currentSecs / totalSecs) * 100, duration: totalSecs};");
            script3Joiner.add("    }");
            script3Joiner.add("  }");
            script3Joiner.add("  return null;");
            script3Joiner.add("}");
            script3Joiner.add("catch(e) {");
            script3Joiner.add("  console.error('获取时间元素进度失败: ' + e.message);");
            script3Joiner.add("return null;");
            script3Joiner.add("}");

            result = ((JavascriptExecutor) driver).executeScript(script3Joiner.toString());
            if (result instanceof Map) {
                Map<?, ?> mapResult = (Map<?, ?>) result;
                if (mapResult.containsKey("progress")) {
                    Object progressObj = mapResult.get("progress");
                    if (progressObj instanceof Long) {
                        return ((Long) progressObj).doubleValue();
                    } else if (progressObj instanceof Double) {
                        return (Double) progressObj;
                    } else if (progressObj instanceof Number) {
                        return ((Number) progressObj).doubleValue();
                    }
                }
            }

            return null; // 所有方法都失败
        } catch (Exception e) {
            log.warn("获取视频进度时发生异常: {}", e.getMessage());
            return null;
        }
    }

    /**
     * 获取视频总长度（秒）
     */
    private Double getVideoDuration(WebDriver driver) {
        try {
            // 方法1: 尝试从标准video元素获取总长度
            StringJoiner script1Joiner = new StringJoiner("\n");
            script1Joiner.add("try {");
            script1Joiner.add("  // 查找页面中所有的video元素");
            script1Joiner.add("  var videos = document.querySelectorAll('video');");
            script1Joiner.add("  for (var i = 0; i < videos.length; i++) {");
            script1Joiner.add("    var video = videos[i];");
            script1Joiner.add("    if (video.duration > 0) {");
            script1Joiner.add("      return video.duration;");
            script1Joiner.add("    }");
            script1Joiner.add("  }");
            script1Joiner.add("  return null;");
            script1Joiner.add("}");
            script1Joiner.add("catch(e) {");
            script1Joiner.add("  console.error('获取视频总长度失败: ' + e.message);");
            script1Joiner.add("  return null;");
            script1Joiner.add("}");

            Double duration = (Double) ((JavascriptExecutor) driver).executeScript(script1Joiner.toString());
            if (duration != null && !Double.isNaN(duration) && duration > 0) {
                return duration;
            }

            // 方法2: 尝试从常见的播放器框架获取总长度
            StringJoiner script2Joiner = new StringJoiner("\n");
            script2Joiner.add("try {");
            script2Joiner.add("  // 尝试获取video.js播放器总长度");
            script2Joiner.add("  if (typeof videojs !== 'undefined') {");
            script2Joiner.add("    var players = videojs.players;");
            script2Joiner.add("    for (var playerId in players) {");
            script2Joiner.add("      if (players.hasOwnProperty(playerId)) {");
            script2Joiner.add("        var player = players[playerId];");
            script2Joiner.add("        var duration = player.duration();");
            script2Joiner.add("        if (duration > 0) {");
            script2Joiner.add("          return duration;");
            script2Joiner.add("        }");
            script2Joiner.add("      }");
            script2Joiner.add("    }");
            script2Joiner.add("  }");
            script2Joiner.add("  return null;");
            script2Joiner.add("}");
            script2Joiner.add("catch(e) {");
            script2Joiner.add("  console.error('获取播放器总长度失败: ' + e.message);");
            script2Joiner.add("  return null;");
            script2Joiner.add("}");

            duration = (Double) ((JavascriptExecutor) driver).executeScript(script2Joiner.toString());
            if (duration != null && !Double.isNaN(duration) && duration > 0) {
                return duration;
            }

            // 方法3: 尝试从时间显示元素获取总长度
            StringJoiner script3Joiner = new StringJoiner("\n");
            script3Joiner.add("try {");
            script3Joiner.add("  // 查找总时间显示元素");
            script3Joiner.add("  var totalTime = null;");
            script3Joiner.add("  var durationElements = document.querySelectorAll('.duration, .time-duration, .video-time-total');");
            script3Joiner.add("  if (durationElements.length > 0) {");
            script3Joiner.add("    totalTime = durationElements[0].textContent.trim();");
            script3Joiner.add("  }");
            script3Joiner.add("  ");
            script3Joiner.add("  // 如果找到时间文本，尝试解析");
            script3Joiner.add("  if (totalTime) {");
            script3Joiner.add("    // 解析时间格式 (例如: 1:23:45 或 23:45)");
            script3Joiner.add("    function parseTime(timeStr) {");
            script3Joiner.add("      var parts = timeStr.split(':').map(Number);");
            script3Joiner.add("      if (parts.length === 3) {");
            script3Joiner.add("        return parts[0] * 3600 + parts[1] * 60 + parts[2]; // 小时:分钟:秒");
            script3Joiner.add("      } else if (parts.length === 2) {");
            script3Joiner.add("        return parts[0] * 60 + parts[1]; // 分钟:秒");
            script3Joiner.add("      }");
            script3Joiner.add("      return 0;");
            script3Joiner.add("    }");
            script3Joiner.add("    ");
            script3Joiner.add("    var totalSecs = parseTime(totalTime);");
            script3Joiner.add("    if (totalSecs > 0) {");
            script3Joiner.add("      return totalSecs;");
            script3Joiner.add("    }");
            script3Joiner.add("  }");
            script3Joiner.add("  return null;");
            script3Joiner.add("}");
            script3Joiner.add("catch(e) {");
            script3Joiner.add("  console.error('获取时间元素总长度失败: ' + e.message);");
            script3Joiner.add("  return null;");
            script3Joiner.add("}");

            duration = (Double) ((JavascriptExecutor) driver).executeScript(script3Joiner.toString());
            if (duration != null && !Double.isNaN(duration) && duration > 0) {
                return duration;
            }

            return null; // 所有方法都失败
        } catch (Exception e) {
            log.warn("获取视频总长度时发生异常: {}", e.getMessage());
            return null;
        }
    }

    /**
     * 检查是否有视频播放完成的视觉标志
     */
    private boolean checkVideoCompleteIndicators(WebDriver driver) {
        try {
            // 检查常见的完成标志
            StringJoiner scriptJoiner = new StringJoiner("\n");
            scriptJoiner.add("try {");
            scriptJoiner.add("  // 检查是否达到目标观看时间（98%的总时间）");
            scriptJoiner.add("  var replayButtons = document.querySelectorAll('.replay-button, .btn-replay, button:contains(\"重播\"), button:contains(\"重新播放\")');");
            scriptJoiner.add("  if (replayButtons.length > 0 && replayButtons[0].offsetParent !== null) {");
            scriptJoiner.add("    return true;");
            scriptJoiner.add("  }");
            scriptJoiner.add("  ");
            scriptJoiner.add("  // 检查视频是否已暂停在结尾处");
            scriptJoiner.add("  var videos = document.querySelectorAll('video');");
            scriptJoiner.add("  for (var i = 0; i < videos.length; i++) {");
            scriptJoiner.add("    var video = videos[i];");
            scriptJoiner.add("    if (video.duration > 0 && video.paused && ");
            scriptJoiner.add("        Math.abs(video.currentTime - video.duration) < 1) {");
            scriptJoiner.add("      return true;");
            scriptJoiner.add("    }");
            scriptJoiner.add("  }");
            scriptJoiner.add("  ");
            scriptJoiner.add("  // 检查页面上是否有完成、结束等文本标志");
            scriptJoiner.add("  var completeTexts = ['已完成', '播放结束', '观看完成', '课程结束'];");
            scriptJoiner.add("  var pageText = document.body.innerText.toLowerCase();");
            scriptJoiner.add("  for (var j = 0; j < completeTexts.length; j++) {");
            scriptJoiner.add("    if (pageText.includes(completeTexts[j].toLowerCase())) {");
            scriptJoiner.add("      return true;");
            scriptJoiner.add("    }");
            scriptJoiner.add("  }");
            scriptJoiner.add("  ");
            scriptJoiner.add("  return false;");
            scriptJoiner.add("}");
            scriptJoiner.add("catch(e) {");
            scriptJoiner.add("  console.error('检查视频完成标志失败: ' + e.message);");
            scriptJoiner.add("  return false;");
            scriptJoiner.add("}");

            return (boolean) ((JavascriptExecutor) driver).executeScript(scriptJoiner.toString());
        } catch (Exception e) {
            log.warn("检查视频完成标志时发生异常: {}", e.getMessage());
            return false;
        }
    }

    /**
     * 查找播放按钮（尝试多种可能的选择器）
     */
    WebElement findPlayButton(WebElement courseItem) {
        try {
            // 首先尝试使用预定义的选择器
            return courseItem.findElement(By.xpath(SelectorConstants.XPATH_LIVE_COURSE_PLAY_BUTTON));
        } catch (Exception e) {
            // 如果找不到，尝试其他常见的播放按钮元素
            String[] fallbackSelectors = {
                    "button[class*='play']",
                    "a[class*='play']",
                    "div[class*='play']",
                    "button[text*='播放']",
                    "a[text*='播放']",
                    "button:contains('播放')",
                    "a:contains('播放')"
            };

            for (String selector : fallbackSelectors) {
                try {
                    List<WebElement> elements = courseItem.findElements(By.cssSelector(selector));
                    if (!elements.isEmpty()) {
                        return elements.get(0);
                    }
                } catch (Exception ex) {
                    // 忽略
                }
            }

            return null;
        }
    }
}